package com.easylinkin.linkappapi.redis;

import com.easylinkin.linkappapi.elasticsearch.service.EtlStatisticMonitorService;
import com.easylinkin.linkappapi.investigation.service.InvestigationTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.RedisKeyExpiredEvent;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.ThreadPoolExecutor;

@Component
@Slf4j
public class RedisKeyExpireListener implements ApplicationListener<RedisKeyExpiredEvent> {

    @Resource
    private RedisSync redisSync;
//    @Autowired
//    private RedisUtil redisUtil;

//    @Resource
//    private DeviceServiceService deviceServiceService;
//    @Resource
//    private AlarmListener alarmListener;
//    @Resource
//    private DeviceAlarmListener deviceAlarmListener;
//    @Resource
//    private DeviceAttributeStatusListener deviceAttributeStatusListener;
//    @Resource
//    private AirMonitorListener airMonitorListener;
//    @Resource
//    private DeviceMonitorListener deviceMonitorListener;
    @Resource
    private InvestigationTaskService investigationTaskService;
    @Resource
    private EtlStatisticMonitorService etlStatisticMonitorService;

//    @Autowired
//    private RedissonClient redisson;
    /**
     * 重发次数
     */
//    private final int RESEND_COUNT = 3;

    static ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();

    static {
        threadPoolTaskExecutor.setCorePoolSize(50);
        threadPoolTaskExecutor.setMaxPoolSize(100);
        threadPoolTaskExecutor.setQueueCapacity(100);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        threadPoolTaskExecutor.afterPropertiesSet();
    }

    /**
     * com.easylinkin.linkappapi.deviceservice.service.impl.DeviceServicesServiceImpl#send(java.util.Map)
     * <p>DeviceServicesServiceImpl#send方法设置redis过期时间 10秒没有等到相应的应答会启动重发机制 最多发3次<p/>
     *
     * @param event 事件
     */
    @Override
    public void onApplicationEvent(RedisKeyExpiredEvent event) {
        String key = new String(event.getId());
        if (key.endsWith("_down")) {
            log.info("key到期触发，开始：" + key);
        } else if (key.endsWith("checkEtlStatisticStillRun")) {
            etlStatisticMonitorService.sendEtlErrorEmail();
        }
//        RLock redissonLock = redisson.getLock(key + "_lock");
//        if (redissonLock.tryLock()) {
//            try {
//                // 只处理是重发下发的逻辑的
//                if (key.endsWith("_down")) {
//                    log.info("key到期触发，抢到锁开始999999：" + key);
//                    resend(key);
//                }else {
//                    threadPoolTaskExecutor.execute(() -> otherKeyExpiredEvent(key));
//                }
//            } catch (Exception ex) {
//                log.error("RedisKeyExpire error:", ex);
//            } finally {
//                redissonLock.unlock();
//            }
//        }

//锁 5分钟 = 300000毫秒
        redisSync.tryAcquireRelease(key, 300000,true, () -> {
            // 只处理是重发下发的逻辑的
            if (key.endsWith("_down")) {
//                resend(key);
            } else {
                threadPoolTaskExecutor.execute(() -> otherKeyExpiredEvent(key));
            }
        });
    }

    private void otherKeyExpiredEvent(String key) {
        if (key.endsWith("_Sms_task")) {
//            sendInvestigationSms(key);
            investigationTaskService.sendInvestigationSms(key + "_param");

        } else {
            log.info("除了down、_Sms_task的其他key失效了：{}", key);
        }
    }


    /**
     * 发送巡检任务的短信
     *
     * @param key
     */
//    private void sendInvestigationSms(String key) {
//        // 发送短信
//        investigationTaskService.sendInvestigationSms(key + "_param");
//    }
/*
    private void resend(String key) {
//      解决本地启动了网络延迟不一致，致使的多次重发,若已重发了标记为已使用
        String usedKey = key + "_resend_used";
        if (redisUtil.hasKey(usedKey)) {
            return;
        }
        log.info("key到期触发，得到了重发的初步允许：" + key);
        redisUtil.set(usedKey, true, 5);
//		    		_lock是为了解决多实例问题 同步锁
        Object obj = redisUtil.get(key + "_param");
        redisUtil.del(key + "_param");
        if (obj != null) {
            Map<String, Object> map = (Map<String, Object>) obj;
            if (map.get("count") != null) {
                Integer count = (Integer) map.get("count");
                if (count >= RESEND_COUNT) {
                    return;
                }
                count++;
                map.put("count", count);
            } else {
                map.put("count", 1);
            }
            log.info("重发，第{}次：{}", map.get("count"), map);
            deviceServiceService.send(map);

        } else {
            log.info("send down param不见了：" + key);
        }

    }*/



}

